﻿using System;
using System.Diagnostics;
using System.Globalization;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Web;
using System.Web.Http;
using System.Web.Http.Dispatcher;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using WebApp.Controllers;
using WebApp.Formatters;

namespace WebApp.Initialization
{
    public class AppStartUpModule : IHttpModule
    {
        private static bool _initialized;
        private static readonly object Lock = new object();
        public static FileVersionInfo VersionInfo;

        public void Init(HttpApplication context)
        {
            context.BeginRequest += BeginRequest;
        }

        public void Dispose() { }

        private static void BeginRequest(object sender, EventArgs e)
        {
            if (_initialized) return;
            lock (Lock)
            {
                if (_initialized) return;
                StartUpMvcApp();
                _initialized = true;
            }
        }

        private static void StartUpMvcApp()
        {
            Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

            VersionInfo = FileVersionInfo.GetVersionInfo(Assembly.GetAssembly(typeof(HomeController)).Location);

            ControllerBuilder.Current.SetControllerFactory(new ControllerFactory());

            GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new SmartHttpControllerActivator());

            AreaRegistration.RegisterAllAreas();

            GlobalConfiguration.Configure(RegisterWebApi);
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            RegisterBundles(BundleTable.Bundles);
            RegisterFormatters();

            KeepAlive.Start();
        }

        private static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("public/*");

            routes.MapRoute("Default", "{controller}/{action}/{id}", new { controller = "Home", action = "Index", id = UrlParameter.Optional });
        }

        private static void RegisterWebApi(HttpConfiguration configuration)
        {
            // Web API configuration and services

            // Web API routes
            configuration.MapHttpAttributeRoutes();

            //configuration.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional });
            //configuration.Routes.MapHttpRoute("ActionWebApiRoute", "api/{controller}/{action}/{id}", new { id = RouteParameter.Optional });

            configuration.Routes.MapHttpRoute("DefaultApiWithId", "api/{controller}/{id}", new { id = RouteParameter.Optional }, new { id = @"\d+" });
            configuration.Routes.MapHttpRoute("DefaultApiWithAction", "api/{controller}/{action}");
            configuration.Routes.MapHttpRoute("DefaultApiGet", "api/{controller}", new { action = "Get" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Get.Method) });
            configuration.Routes.MapHttpRoute("DefaultApiPost", "api/{controller}", new { action = "Post" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Post.Method) });
            configuration.Routes.MapHttpRoute("DefaultApiPut", "api/{controller}", new { action = "Put" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Put.Method) });
            configuration.Routes.MapHttpRoute("DefaultApiDelete", "api/{controller}", new { action = "Delete" }, new { httpMethod = new HttpMethodConstraint(HttpMethod.Delete.Method) });
        }

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new StyleBundle("~/bundles/bootstrapcss")
                .Include("~/Public/css/bootstrap.css", new CssRewriteUrlTransform())
                .Include("~/Public/css/moment.datepicker.css", new CssRewriteUrlTransform())
                .Include("~/Public/css/font-awesome.css", new CssRewriteUrlTransform()));

            bundles.Add(new StyleBundle("~/bundles/screencss")
                .Include("~/Public/vendor/owl-carousel/owl.carousel.css", new CssRewriteUrlTransform())
                .Include("~/Public/vendor/owl-carousel/owl.theme.css", new CssRewriteUrlTransform())
                .Include("~/Public/vendor/circle-flip-slideshow/css/component.css", new CssRewriteUrlTransform())
                .Include("~/Public/vendor/rs-plugin/css/settings.css",new CssRewriteUrlTransform())
                .Include("~/Public/vendor/magnific-popup/magnific-popup.css", new CssRewriteUrlTransform()));

            bundles.Add(new StyleBundle("~/bundles/themecss")
                .Include("~/Public/css/theme.css", new CssRewriteUrlTransform())
                .Include("~/Public/css/theme-elements.css", new CssRewriteUrlTransform())
                .Include("~/Public/css/theme-animate.css", new CssRewriteUrlTransform()));

            bundles.Add(new StyleBundle("~/bundles/overriddencss")
                .Include("~/Public/css/skin.css", new CssRewriteUrlTransform())
                .Include("~/Public/css/custom.css", new CssRewriteUrlTransform())
                .Include("~/Public/css/theme-responsive.css", new CssRewriteUrlTransform())
                .Include("~/Public/css/site.css", new CssRewriteUrlTransform()));

            bundles.Add(new ScriptBundle("~/bundles/headlibs").Include(
                "~/Public/vendor/modernizr.js",
                "~/Public/vendor/jquery.js",
                "~/Public/vendor/jquery.plugins.js",
                "~/Public/vendor/jquery.easing.js",
                "~/Public/vendor/jquery.appear.js",
                "~/Public/vendor/jquery.cookie.js",
                "~/Public/vendor/jquery.pubsub.js",
                "~/Public/vendor/jquery.shortcut.js",
                "~/Public/vendor/json2.js",
                "~/Public/vendor/knockout.js",
                "~/Public/vendor/moment.js",
                "~/Public/vendor/underscore.js",
                "~/Public/api/date.extensions.js",
                "~/Public/vendor/conversion.js",
                "~/Public/vendor/bootstrap.js"));

            bundles.Add(new ScriptBundle("~/bundles/libs").Include(
              "~/Public/vendor/moment.datepicker.js",
              "~/Public/vendor/moment.datepicker.ko.js",
              "~/Public/api/theme.js",
              "~/Public/api/knockout.extensions.js",
               "~/Public/vendor/twitterjs/twitter.js",
              "~/Public/vendor/owl-carousel/owl.carousel.js",
              "~/Public/vendor/jflickrfeed/jflickrfeed.js",
              "~/Public/vendor/magnific-popup/magnific-popup.js"));

            BundleTable.EnableOptimizations = true;
        }

        private static void RegisterFormatters()
        {
            var jsonSettings = new JsonSerializerSettings
            {
                ContractResolver = new CamelCasePropertyNamesContractResolver(),
                DateFormatHandling = DateFormatHandling.IsoDateFormat,
            };

            GlobalConfiguration.Configuration.Formatters.Insert(0, new JsonNetFormatter(jsonSettings));
        }
    }
}